﻿using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Operations;
using PC.PickleJar.Trello.Data;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PC.PickleJar.Trello.VisualStudio
{
	internal class QuickInfoSource : IQuickInfoSource
	{
		private const String TrelloUrlPrefix = "://trello.com/c/";
		private const int IdLength = 8;

		private bool isDisposed;

		private QuickInfoSourceProvider provider;
		private ITextBuffer subjectBuffer;
		private Dictionary<String, String> dictionary;
		private CardRepository repository;

		public QuickInfoSource(QuickInfoSourceProvider provider, ITextBuffer subjectBuffer)
		{
			this.provider = provider;
			this.subjectBuffer = subjectBuffer;
			this.repository = new CardRepository(HardCodedConfig.DeveloperApiKey, HardCodedConfig.UserToken);

			this.dictionary = new Dictionary<string, string>();
		}

		public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> quickInfoContent, out ITrackingSpan applicableToSpan)
		{
			applicableToSpan = null;

			foreach (var item in quickInfoContent)
			{
				if (item is String)
				{
					String stringItem = (String)item;

					if (stringItem.ToLower().StartsWith("http" + QuickInfoSource.TrelloUrlPrefix) ||
						stringItem.ToLower().StartsWith("https" + QuickInfoSource.TrelloUrlPrefix))
					{
						var urlCandidate = stringItem.Split()[0];

						String cardName = this.GetCardName(urlCandidate);

						if (!String.IsNullOrWhiteSpace(cardName))
						{
							var index = quickInfoContent.IndexOf(item);
							if (index >= 0)
							{
								quickInfoContent[index] =
									String.Format(
										CultureInfo.CurrentCulture,
										"{0}{2}{2}{1}",
										cardName,
										stringItem,
										Environment.NewLine);

								this.SetApplicableToSpan(session, ref applicableToSpan);
							}

							break;
						}
					}
				}
			}
		}

		private void SetApplicableToSpan(IQuickInfoSession session, ref ITrackingSpan applicableToSpan)
		{
			// Map the trigger point down to our buffer.
			SnapshotPoint? subjectTriggerPoint = session.GetTriggerPoint(this.subjectBuffer.CurrentSnapshot);
			if (!subjectTriggerPoint.HasValue)
			{
				applicableToSpan = null;
				return;
			}

			ITextSnapshot currentSnapshot = subjectTriggerPoint.Value.Snapshot;
			SnapshotSpan querySpan = new SnapshotSpan(subjectTriggerPoint.Value, 0);
			applicableToSpan = currentSnapshot.CreateTrackingSpan
				(
				querySpan.Start, 0, SpanTrackingMode.EdgeInclusive
				);
		}

		private String GetCardName(String shortUrl)
		{
			if (!this.dictionary.ContainsKey(shortUrl))
			{
				var card = this.repository.GetCardByShortLink(shortUrl);
				if (card != null)
				{
					this.dictionary.Add(shortUrl, card.name);
				}
			}

			String value;
			this.dictionary.TryGetValue(shortUrl, out value);

			return value;
		}

		public void Dispose()
		{
			if (!this.isDisposed)
			{
				GC.SuppressFinalize(this);
				this.isDisposed = true;
			}
		}
	}
}
